package org.ikit.twitter;

import processing.core.*;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import jxl.*;
import jxl.read.biff.BiffException;
import jxl.write.*;
import jxl.write.Number;
import jxl.write.biff.RowsExceededException;

public class TwitterProcessingVis extends PApplet {

    private static final int ROW_SPACING = 25;
    private static final float X_SCALE = (float) (1.0 / 120.0);
    String FILE_URL_BASE = "data/";
    String EXCEL_FILE_EXTENSION = ".xls";
    String inputFileName = //"kbsi";
            //"edmedia10";
            //"MLA09";
            //"ISTE10";
            //"4IPC2010";
            //"cni10s";
            //"CPUO";
            //"geoinst";
            //"npc2010";
            //"lak11";
            "aera2011";
    // Map of twitterers (might have some problem with from_user_id because of raw data)
    Map<String, TweepObject> twitterers = new TreeMap<String, TweepObject>();
    Map<Integer, String> idNameMap = new TreeMap<Integer, String>();
    Map<String, Integer> nameIdMap = new TreeMap<String, Integer>();
    // Map of tweets
    Map<String, List<TweetObject>> tweets = new TreeMap<String, List<TweetObject>>();
    Map<String, List<String>> rtMap = new TreeMap<String, List<String>>(); //<BeRTUser, List<RTUser>>
    Map<String, List<String>> msgMap = new TreeMap<String, List<String>>(); //<ToUser, List<FromUser>>
    Long beginDateSeconds;
    Long endDateSeconds;
    float xScale;
    boolean alreadyReadExcel = false;
    private PFont font;
    //PeasyCam cam;
    int camLookAtX, camLookAtY, camDistance;

    @Override
    public void setup() {

        try {
            readExcelData();
        } catch (RowsExceededException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (WriteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        int width = 2000;//40 + (int) (xScale * (endDateSeconds - beginDateSeconds));//1440,
        int height = ROW_SPACING * (nameIdMap.size() + 1);
        //width = 1024; height = 768;
        size(width, height, P2D);
        System.out.println("Canvas size: " + width + "*" + height);

        /*camLookAtX = width/2;
        camLookAtY = height/2;
        camDistance = 600;
        cam = new PeasyCam(this,camLookAtX, camLookAtY, 0, 600);
        cam.setResetOnDoubleClick(false);
        cam.setMinimumDistance(.001f);
        cam.setMaximumDistance(50000);*/

        colorMode(RGB);
        background(color(0, 0, 0));
        smooth();
        font = createFont("FFScala", 96);

        noLoop();
    }

    private void readExcelData() throws RowsExceededException, WriteException {
        // it is weird why this function is excecuted for twice...
        if (alreadyReadExcel) {
            return;
        }
        alreadyReadExcel = true;

        // Initialize Excel data
        Workbook workbook = null;
        try {
            File inputFile = new File(FILE_URL_BASE + inputFileName + EXCEL_FILE_EXTENSION);
            workbook = Workbook.getWorkbook(inputFile);
        } catch (BiffException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Sheet sheet = workbook.getSheet(0);

        //int cols = sheet.getColumns();
        int rows = sheet.getRows();

        System.out.println(rows);

        // Initialize name_id and id_name map
        int userCount = 0;
        for (int i = 0; i < rows; i++) {
            if (sheet.getCell(0, i).getContents().equalsIgnoreCase("")) {
                break;
            }

            String fromUser = sheet.getCell(2, i).getContents().toLowerCase();
            //System.out.println(sheet.getCell(4, i).getContents());
            int fromUserId = userCount + 1;
            if (sheet.getCell(4, i).getType() != CellType.EMPTY) {
                fromUserId = (int) ((NumberCell) sheet.getCell(4, i)).getValue();
            }
            String userProfileURL = sheet.getCell(7, i).getContents();
            if (!twitterers.containsKey(fromUser)) {
                userCount++;
                TweepObject aTwitterer = new TweepObject(fromUser, fromUserId, userProfileURL);
                twitterers.put(fromUser, aTwitterer);
                idNameMap.put(fromUserId, fromUser);
                nameIdMap.put(fromUser, fromUserId);
            }
        }

        // Set begin and end date, and set the scale of x axis
        // I set the begin and end tweet by hand:
        // 19 - 652 for EdMedia10 314
        // 36 - 1678 for MLA09
        // 25 - 460 for cni10s (day1: 25 - 265; day2: 266 - 460)
        // 1 - 949 for CPUO
        // 82 - 1648 for geoinst (May25: 85-862; May26: 874-1097; May27: 1099 - 1648)
        // 202 - 694 for npc2010
        try {
            beginDateSeconds = new Long(sheet.getCell(12, 0).getContents()); //0
            endDateSeconds = new Long(sheet.getCell(12, rows - 1).getContents()); //rows-1
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("no milliseconds info. use date string.");
            //java.text.DateFormat df = new SimpleDateFormat("EEE, DD MMM yyyy HH:mm:ss Z");
            java.text.DateFormat df = new SimpleDateFormat("DD MMM yyyy HH:mm:ss");
            try {
                Date beginDate = df.parse(sheet.getCell(11, 0).getContents());
                Date endDate = df.parse(sheet.getCell(11, rows - 1).getContents());
                beginDateSeconds = beginDate.getTime();
                endDateSeconds = endDate.getTime();
            } catch (ParseException e1) {
                System.out.println("data string passing error.");
                e1.printStackTrace();
            }
        }
        xScale = (float) (1400.0 / (endDateSeconds - beginDateSeconds));
        //xScale = X_SCALE;

        // Read tweet data
        for (int i = 0; i < rows; i++) {
            // get tweet text
            String text = sheet.getCell(0, i).getContents();
            //System.out.println(text);
            // get to_user_id
            int toUserId = 0;
            if (sheet.getCell(1, i).getType() != CellType.EMPTY) {
                toUserId = (int) ((NumberCell) sheet.getCell(1, i)).getValue();
            }
            // get from_user_name
            String fromUser = sheet.getCell(2, i).getContents().toLowerCase();
            // get from_user_id
            int fromUserId = nameIdMap.get(fromUser);
            if (sheet.getCell(4, i).getType() != CellType.EMPTY)
                fromUserId = (int) ((NumberCell) sheet.getCell(4, i)).getValue();
            // get created_at
            long timeSeconds = 0;
            try {
                timeSeconds = new Integer(sheet.getCell(12, i).getContents());
            } catch (ArrayIndexOutOfBoundsException e) {
                //System.out.println("no milliseconds info. use date string.");
                java.text.DateFormat df = new SimpleDateFormat("EEE, DD MMM yyyy HH:mm:ss Z");
                df = new SimpleDateFormat("DD MMM yyyy HH:mm:ss");
                try {
                    Date d = df.parse(sheet.getCell(11, i).getContents());
                    timeSeconds = d.getTime();
                } catch (ParseException e1) {
                    System.out.println("data string passing error.");
                    e1.printStackTrace();
                }
            }
            //System.out.println(fromUser + " " + time);


            // Add this tweet to tweets map
            TweetObject aTweet = new TweetObject(fromUser, fromUserId, toUserId, text, timeSeconds);
            if (text.startsWith("@") && fromUserId != toUserId) { // && fromUserId!=toUserId
                aTweet.setType(TweetObject.TWEET_TYPE_MESSAGE);
                if (toUserId == 0) {
                    String toUser = text.substring(1,
                            text.indexOf(" ") > text.indexOf(":") ? text.indexOf(" ") : text.indexOf(":"));
                    if (nameIdMap.containsKey(toUser)) {
                        toUserId = nameIdMap.get(toUser);
                    } else {
                        userCount++;
                        TweepObject aTwitterer = new TweepObject(toUser, toUserId, "");
                        twitterers.put(toUser, aTwitterer);
                        idNameMap.put(toUserId, toUser);
                        nameIdMap.put(toUser, toUserId);
                    }
                }

                aTweet.setToUserId(toUserId);
                String toUser = idNameMap.get(toUserId);
                aTweet.setToUser(toUser);
                if (toUser != null & !fromUser.equals(toUser) && nameIdMap.containsKey(toUser)) {
                    //System.out.println(text + "/n" + fromUser + toUser);
                    if (msgMap.containsKey(toUser)) {
                        msgMap.get(toUser).add(fromUser);
                    } else {
                        List fromList = new ArrayList();
                        fromList.add(fromUser);
                        msgMap.put(toUser, fromList);
                    }
                }
            } else if (text.indexOf("@") > 0 && text.startsWith("RT")) {
                aTweet.setType(TweetObject.TWEET_TYPE_RETWEET);
                if (text.indexOf(':') > 0
                        && text.indexOf(':') > text.indexOf('@')
                        && text.indexOf(':') - text.indexOf('@') <= 16) {
                    String toUser = text.substring(text.indexOf('@') + 1, text.indexOf(':')).toLowerCase();
                    aTweet.setToUser(toUser);
                    if (idNameMap.containsKey(toUserId) && nameIdMap.containsKey(toUser)) {
                        aTweet.setToUserId(nameIdMap.get(toUser));
                    }

                    if (toUser != null && nameIdMap.containsKey(toUser)) {
                        if (rtMap.containsKey(toUser)) {
                            rtMap.get(toUser).add(fromUser);
                        } else {
                            List fromList = new ArrayList();
                            fromList.add(fromUser);
                            rtMap.put(toUser, fromList);
                        }
                    }
                } else {
                    System.out.println("Bad Retweet Format Error: " + text);
                    String tmpStr = text.substring(text.indexOf('@') + 1).trim();
                    // In case the problem is caused by missing ":"
                    if (tmpStr.indexOf(' ') <= 16 && tmpStr.indexOf(' ') > 0) {
                        String toUser = tmpStr.substring(0, tmpStr.indexOf(' ')).toLowerCase();
                        aTweet.setToUser(toUser);
                        if (idNameMap.get(toUserId) != null && nameIdMap.get(toUser) != null) {
                            aTweet.setToUserId(nameIdMap.get(toUser));
                        }

                        if (toUser != null && nameIdMap.containsKey(toUser)) {
                            if (rtMap.containsKey(toUser)) {
                                rtMap.get(toUser).add(fromUser);
                            } else {
                                List fromList = new ArrayList();
                                fromList.add(fromUser);
                                rtMap.put(toUser, fromList);
                            }
                        }
                    }
                }
            } else {
                aTweet.setType(TweetObject.TWEET_TYPE_ORDINARY);
            }
            List<TweetObject> currentList;
            if (tweets.containsKey(fromUser)) {
                currentList = tweets.get(fromUser);
            } else {
                currentList = new ArrayList<TweetObject>();
            }
            currentList.add(aTweet);
            tweets.put(fromUser, currentList);
        }

        Iterator it = tweets.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, List<TweetObject>> me = (Map.Entry) it.next();
            TweepObject author = (TweepObject) twitterers.get(me.getKey());
            author.setTweetCount(me.getValue().size());
            //System.out.println(author.getName() + " - " + me.getValue().size());
        }

        it = rtMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, List<String>> me = (Map.Entry) it.next();
            TweepObject author = (TweepObject) twitterers.get(me.getKey());
            author.setRtCount(me.getValue().size());
            //System.out.println(author.getName() + " - " + me.getValue().size());
        }

        it = msgMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, List<String>> me = (Map.Entry) it.next();
            TweepObject author = (TweepObject) twitterers.get(me.getKey());
            author.setMessageCount(me.getValue().size());
            //System.out.println(author.getName() + " - " + me.getValue().size());
        }

        try {
            createUcinetData();
            //createLSAData();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private void createLSAData() throws IOException {
        BufferedWriter jsFileWriter = new BufferedWriter(new FileWriter(FILE_URL_BASE + "miserables_" + inputFileName + ".js"));

        StringBuffer nodesBuffer = new StringBuffer();
        StringBuffer linksBuffer = new StringBuffer();

        nodesBuffer.append("var miserables = {" + System.getProperty("line.separator"));
        nodesBuffer.append("nodes:[" + System.getProperty("line.separator"));

        linksBuffer.append("]," + System.getProperty("line.separator")
                + "links:[" + System.getProperty("line.separator"));

        List userList = new ArrayList(tweets.keySet());
        for (int i = 0; i < userList.size(); i++) {
            String author = (String) userList.get(i);
            TweepObject authorObj = (TweepObject) twitterers.get(author);

            nodesBuffer.append("{nodeName:\"" + author
                    + "\", group:" + authorObj.getTweetCount()
                    + "}," + System.getProperty("line.separator"));

            for (int j = 0; j < userList.size(); j++) {
                String anotherAuthor = (String) userList.get(j);
                double closeness = calculateUserCloseness(author, anotherAuthor);
                //afWriter.write(new Double(dist).toString() + " ");
                if (closeness > 0) {
                    //afWriter.write(author + " " + anotherAuthor + " " +
                    //		closeness + System.getProperty("line.separator"));
                    linksBuffer.append("{source:" + i + ", target:" + j + ", value:"
                            + closeness + "}," + System.getProperty("line.separator"));
                }
            }
            //nfWriter.append(afWriter.toString());
        }
        System.out.println("+" + nodesBuffer.charAt(nodesBuffer.length() - 3) + "+");
        nodesBuffer.deleteCharAt(nodesBuffer.length() - 3);
        linksBuffer.deleteCharAt(linksBuffer.length() - 3);
        linksBuffer.append("]" + System.getProperty("line.separator") + "};");

        jsFileWriter.write(nodesBuffer.toString());
        jsFileWriter.write(linksBuffer.toString());
        //System.out.println(attibutesBuffer.toString());
        //afWriter.close();
        jsFileWriter.close();
    }

    private void createUcinetData() throws IOException, RowsExceededException, WriteException {
        BufferedWriter nfWriter = new BufferedWriter(new FileWriter("C:\\Users\\Bodong\\Documents\\UCINET data\\Twitter\\nodes_" + inputFileName + ".txt"));
        //BufferedWriter afWriter = new BufferedWriter(new FileWriter("C:\\Users\\Bodong\\Documents\\UCINET data\\Twitter\\attributes.txt"));
        File outputExcel = new File(FILE_URL_BASE + inputFileName + "_spss" + EXCEL_FILE_EXTENSION);
        WritableWorkbook workbook = Workbook.createWorkbook(outputExcel);
        WritableSheet sheet = workbook.createSheet("users", 0);

        StringBuffer attibutesBuffer = new StringBuffer();

        nfWriter.write("*Node data" + System.getProperty("line.separator"));
        nfWriter.write("ID, tweetCount, rtCount, msgCount, rtScale, msgScale" + System.getProperty("line.separator"));

        Label label1 = new Label(0, 0, "ID");
        sheet.addCell(label1);
        Label label2 = new Label(1, 0, "tweetCount");
        sheet.addCell(label2);
        Label label3 = new Label(2, 0, "rtCount");
        sheet.addCell(label3);
        Label label4 = new Label(3, 0, "msgCount");
        sheet.addCell(label4);

        /*afWriter.write("dl" + System.getProperty("line.separator"));
        afWriter.write("n = " + tweets.size() + System.getProperty("line.separator"));
        afWriter.write("format = fullmatrix" + System.getProperty("line.separator"));
        afWriter.write("data:" + System.getProperty("line.separator"));*/
        //afWriter.write("*Tie data" + System.getProperty("line.separator"));
        //afWriter.write("from to dist" + System.getProperty("line.separator"));
        attibutesBuffer.append("*Tie data" + System.getProperty("line.separator"));
        attibutesBuffer.append("from to closeness" + System.getProperty("line.separator"));

        List userList = new ArrayList(tweets.keySet());
        for (int i = 0; i < userList.size(); i++) {
            String author = (String) userList.get(i);
            TweepObject authorObj = (TweepObject) twitterers.get(author);

            nfWriter.write(author + " " + authorObj.getTweetCount() + " " + authorObj.getRtCount()
                    + " " + authorObj.getMessageCount() + " " + ((int) Math.sqrt(authorObj.getRtCount()))
                    + " " + ((int) Math.sqrt(authorObj.getMessageCount())) + System.getProperty("line.separator"));

            // Write to excel file
            Label label = new Label(0, i + 1, author);
            sheet.addCell(label);
            Number number1 = new Number(1, i + 1, authorObj.getTweetCount());
            sheet.addCell(number1);
            Number number2 = new Number(2, i + 1, authorObj.getRtCount());
            sheet.addCell(number2);
            Number number3 = new Number(3, i + 1, authorObj.getMessageCount());
            sheet.addCell(number3);

            for (int j = 0; j < userList.size(); j++) {
                String anotherAuthor = (String) userList.get(j);
                double closeness = calculateUserCloseness(author, anotherAuthor);
                //afWriter.write(new Double(dist).toString() + " ");
                if (closeness > 0) {
                    //afWriter.write(author + " " + anotherAuthor + " " +
                    //		closeness + System.getProperty("line.separator"));
                    attibutesBuffer.append(author + " " + anotherAuthor + " "
                            + closeness + System.getProperty("line.separator"));
                }
            }
            //nfWriter.append(afWriter.toString());
        }
        nfWriter.write(attibutesBuffer.toString());
        //System.out.println(attibutesBuffer.toString());
        //afWriter.close();
        nfWriter.close();

        workbook.write();
        workbook.close();
    }

    private double calculateUserCloseness(String author, String anotherAuthor) {
        if (author.equals(anotherAuthor)) {
            return 0;
        }
        List<String> rtList1 = rtMap.get(author);
        List<String> rtList2 = rtMap.get(anotherAuthor);
        List<String> msgList1 = msgMap.get(author);
        List<String> msgList2 = msgMap.get(anotherAuthor);

        int totalRTCount = 0, totalMsgCount = 0;

        if (rtList1 != null) {
            for (String str : rtList1) {
                if (str.equals(anotherAuthor)) {
                    totalRTCount++;
                }
            }
        }

        if (rtList2 != null) {
            for (String str : rtList2) {
                if (str.equals(author)) {
                    totalRTCount++;
                }
            }
        }

        if (msgList1 != null) {
            for (String str : msgList1) {
                if (str.equals(anotherAuthor)) {
                    totalMsgCount++;
                }
            }
        }
        if (msgList2 != null) {
            for (String str : msgList2) {
                if (str.equals(author)) {
                    totalMsgCount++;
                }
            }
        }

        return totalMsgCount + 0.5 * totalRTCount;
        //return 1/(1+ totalMsgCount + 0.25*totalRTCount);
    }

    public void draw() {
        Object[] sortedNames = tweets.keySet().toArray();
        // Sort users by their tweet counts
        for (int pass = 1; pass < sortedNames.length; pass++) {
            for (int i = 0; i < sortedNames.length - pass; i++) {
                TweepObject aUser = twitterers.get(sortedNames[i]);
                TweepObject anotherUser = twitterers.get(sortedNames[i + 1]);
                if (aUser.getTweetCount() < anotherUser.getTweetCount()) {
                    String tmpStr = (String) sortedNames[i];
                    sortedNames[i] = sortedNames[i + 1];
                    sortedNames[i + 1] = tmpStr;
                }
            }
        }

        int tweetCount = 0;
        for (int i = 0; i < sortedNames.length; i++) {
            //TwittererObject aUser = twitterers.get(sortedNames[i]);
            //System.out.println(sortedNames[i] + "---" + aUser.getTweetCount());

            // Draw a line for the user
            int y = (i + 1) * ROW_SPACING;

            stroke(25, 25, 25);
            line(20, y, width - 20, y);

            String user = (String) sortedNames[i];

            //textFont(font, 5);
            //text(user, 20, y);

            List<TweetObject> userTweets = tweets.get(user);
            //System.out.println(user + " listSize " + userTweets.size());
            for (int j = 0; j < userTweets.size(); j++) {
                TweetObject aTweet = userTweets.get(j);
                String text = aTweet.getText();

                int x = (int) (20 + (aTweet.getTimeSeconds() - beginDateSeconds) * xScale);

                if (aTweet.getType() != TweetObject.TWEET_TYPE_ORDINARY) {
                    int toX = x - 20, toY = -5;
                    String toUser = aTweet.getToUser();

                    // Find index of user
                    int index = -1;
                    Object[] tmpSortedNames = sortedNames.clone();
                    for (int m = 0; m < tmpSortedNames.length; m++) {
                        String tmpName = (String) tmpSortedNames[m];
                        if (tmpName.equals(toUser)) {
                            index = m;
                            break;
                        }
                    }

                    // If we find the to_user in user list
                    if (index != -1) { // toUser might be not in the user list
                        toY = (index + 1) * ROW_SPACING;
                        ArrayList<TweetObject> toUserTweets = (ArrayList<TweetObject>) tweets.get(toUser);

                        if (toUserTweets != null) {
                            if (aTweet.getType() == TweetObject.TWEET_TYPE_RETWEET) {
                                // retweet whom? retweet what tweet?
                                for (TweetObject toUserTweet : toUserTweets) {
                                    if (text.indexOf(':') < 0) {
                                        continue;
                                    }
                                    int startIndex = text.indexOf(':') + 2;
                                    int endIndex = startIndex + 25;
                                    if (endIndex > text.length()) {
                                        endIndex = text.length() - 1;
                                    }
                                    String startStr = text.substring(startIndex, endIndex).trim();
                                    if (toUserTweet.getText().startsWith(startStr)) {
                                        //System.out.println("userTweet: " + aTweet.getFromUser() + aTweet.getText());
                                        //System.out.println("toUserTweet: " + toUserTweet.getText());
                                        toX = (int) (20 + (toUserTweet.getTimeSeconds() - beginDateSeconds) * xScale);
                                        break;
                                    }

                                    // @TODO get this part more intelligent
                                }
                                stroke(100, 100, 100);
                                line(toX, toY, x, y);
                            } else if (aTweet.getType() == TweetObject.TWEET_TYPE_MESSAGE) {
                                // message to whom? is it a conversation; if yes, reply to what tweet?
                                // how to represent start? how to represent conversation?
                                boolean isReply = false;
                                for (int n = toUserTweets.size() - 1; n >= 0; n--) {
                                    TweetObject toUserTweet = toUserTweets.get(n);
                                    //System.out.println(toUserTweet.getTimeSeconds());
                                    if (aTweet.compareTo(toUserTweet) > 0
                                            && toUserTweet.getText().startsWith("@" + user)) {
                                        toX = (int) (20 + (toUserTweet.getTimeSeconds() - beginDateSeconds) * xScale);
                                        isReply = true;
                                        //System.out.println(aTweet.getText());
                                        //System.out.println("\t" + toUserTweet.getText());
                                        break;
                                    }
                                }

                                // It is not a reply. Need to find the latest tweet of to_user
                                if (!isReply) {
                                    if (aTweet.compareTo(toUserTweets.get(0)) < 0) {
                                        toX = -10;
                                    } else if (aTweet.compareTo(toUserTweets.get(toUserTweets.size() - 1)) > 0) {
                                        toX = (int) (20 + (toUserTweets.get(toUserTweets.size() - 1).getTimeSeconds() - beginDateSeconds) * xScale);
                                    } else {
                                        int n = toUserTweets.size() - 1;
                                        for (; n > 0; n--) {
                                            TweetObject currentTweet = toUserTweets.get(n);
                                            TweetObject earlierTweet = toUserTweets.get(n - 1);
                                            if (aTweet.compareTo(currentTweet) < 0
                                                    && aTweet.compareTo(earlierTweet) > 0) {
                                                //System.out.println(aTweet.getText());
                                                //System.out.println("\t" + earlierTweet.getText());
                                                toX = (int) (20 + (earlierTweet.getTimeSeconds() - beginDateSeconds) * xScale);
                                                break;
                                            }
                                        }
                                    }
                                }
                                //System.out.println(toX + " "+ toY + "; " + x + " " + y);
                                stroke(0, 100, 0);
                                line(toX, toY, x, y);
                            }
                        }
                    }
                }

                // Draw the tweet box
                fill(255, 0, 0);
                stroke(25, 25, 25);
                rectMode(CENTER);
                rect(x, y, 5, 5);
                tweetCount++;
            }
        }

        //System.out.println(tweetCount);

        //save("visualization.tif");
        saveFrame();
    }
    /*public void keyPressed(){
    System.out.println("HERE");
    if (keyCode == LEFT) camLookAtX -= 20;
    if (keyCode == RIGHT) camLookAtX += 20;
    if (keyCode == UP) camLookAtY -= 20;
    if (keyCode == DOWN) camLookAtY += 20;
    if (key == 'i') camDistance -= 20;
    if (key == 'o') camDistance += 20;
    }*/
    /*static public void main(String args[]) {
    PApplet.main(new String[] { "--bgcolor=#c0c0c0", "org.ikit.twitter.TwitterVis" });
    }*/
}
